package poketrade.tests;

import java.rmi.RemoteException;
import java.util.List;

import javax.naming.Context;
import javax.naming.InitialContext;

import poketrade.entities.Carte;
import poketrade.entities.PendingOffer;
import poketrade.entities.User;
import poketrade.managers.AcheterCredsManager;
import poketrade.managers.CardsManager;
import poketrade.managers.DealManager;
import poketrade.managers.NewsManager;
import poketrade.managers.UserManager;
import junit.framework.TestCase;

public class Test extends TestCase {
	
	AcheterCredsManager acheterCredsManager;
	CardsManager cardsManager;
	DealManager dealManager;
	NewsManager newsManager;
	UserManager userManager;
	
	public Test()
	{
		super();
	}
	
	protected void setUp() throws Exception {
		Context jndiContext = new InitialContext();
		acheterCredsManager = (AcheterCredsManager) jndiContext.lookup("java:module/AcheterCredsManager");
		cardsManager = (CardsManager) jndiContext.lookup("java:module/CardsManager");
		dealManager = (DealManager) jndiContext.lookup("java:module/DealManager");
		newsManager = (NewsManager) jndiContext.lookup("java:module/NewsManager");
		userManager = (UserManager) jndiContext.lookup("java:module/UserManager");
	}
	
	public void testUserManager() throws RemoteException {
		User testUser = new User();
		testUser.setPseudo("testuser");
		testUser.setSha1Password("pipo");
		testUser.setAdresse("Test address");
		
		testUser = userManager.subscribe(testUser);
		assertNotNull(testUser);
		
		User returnedUser = userManager.handleLogin("testuser", "pipo");
		assertNotNull(returnedUser);
		
		assertEquals(testUser.getPseudo(), returnedUser.getPseudo());
		assertEquals(testUser.getPassword(), returnedUser.getPassword());
		assertEquals(testUser.getId(), returnedUser.getId());
		assertEquals(testUser.getAdresse(), returnedUser.getAdresse());
		
		userManager.deleteUser(testUser.getId());
		
		returnedUser = userManager.handleLogin("testuser", "pipo");
		assertNull(returnedUser);
	}
	
	public void testCardsManager() throws RemoteException {
		assertTrue(Carte.hasValidFormat("123/22"));
		assertFalse(Carte.hasValidFormat("123"));
		assertFalse(Carte.hasValidFormat("Pipo"));
		Carte c = new Carte();
		try {
			c.setCardIndex("42/42");
		} catch (poketrade.entities.subtypes.InvalidCardIndex e) {
			assert(false);
		}
		c.setDescription("Test description");
		c.setNom("Pikachu");
		c.setImage(new byte [] { 2, 5, 25, 42 });
		c = cardsManager.registerCard(c);
		assertNotNull(c);
		
		assertNull(cardsManager.getCardById("123/22"));
		
		Carte c2 = cardsManager.getCardById("42/42");
		assertNotNull(c2);
		
		assertEquals(c.getCardIndex(), c2.getCardIndex());
		assertEquals(c.getNom(), c2.getNom());
		assertEquals(c.getDescription(), c2.getDescription());
		for (int i = 0 ; i < c.getImage().length ; i++)
			assertEquals(c.getImage()[i], c2.getImage()[i]);
		
		cardsManager.removeCard(c2.getCardIndex());
		
		assertNull(cardsManager.getCardById("42/42"));
	}

	public void testAcheterCredsManager() throws RemoteException {
		User testUser = new User();
		testUser.setPseudo("testachat");
		testUser.setSha1Password("pipo");
		testUser.setAdresse("Test address");
		testUser.setSolde(0.f);
		
		testUser = userManager.subscribe(testUser);
		
		testUser = acheterCredsManager.acheter(testUser.getId(), 250.f);
		
		User gottenUser = userManager.handleLogin("testachat", "pipo");
		assertEquals(gottenUser.getSolde(), testUser.getSolde());
		assertEquals(gottenUser.getSolde(), 250.f);
		
		userManager.deleteUser(gottenUser.getId());
	}
	
	public void testDealManagerPublishOffer() throws RemoteException {
		assertNull(dealManager.publishOffer(123, "22/22", 10));
		
		User offerer = new User();
		offerer.setPseudo("testdeal");
		offerer.setSha1Password("pipo");
		offerer.setSolde(0.f);
		
		offerer = userManager.subscribe(offerer);
		
		assertNull(dealManager.publishOffer(offerer.getId(), "22/22", 10));

		Carte c = new Carte();
		try {
			c.setCardIndex("22/22");
		} catch (poketrade.entities.subtypes.InvalidCardIndex e) {
			assert(false);
		}
		c.setDescription("Test description");
		c.setNom("Pikachu");
		c.setImage(new byte [] { 2, 5, 25, 42 });
		c = cardsManager.registerCard(c);
		
		offerer = dealManager.publishOffer(offerer.getId(), c.getCardIndex(), 10);
		
		User gottenUser = dealManager.fetchPendingOffersForUser(offerer);
		assertEquals(offerer.getOffers().size(), 1);
		assertEquals(gottenUser.getOffers().size(), 1);
		
		PendingOffer o1 = offerer.getOffers().get(0);
		PendingOffer o2 = gottenUser.getOffers().get(0);
		assertEquals(o1.getBasePrice(), o2.getBasePrice());
		assertEquals(o1.getOfferer().getId(), offerer.getId());
		assertEquals(o1.getOfferer().getId(), o2.getOfferer().getId());
		assertEquals(o1.getOffer().getCardIndex(), c.getCardIndex());
		assertEquals(o2.getOffer().getCardIndex(), c.getCardIndex());
		
		PendingOffer o3 = null;
		List<PendingOffer> offers = dealManager.getOffers();
		for (int i = 0 ; i < offers.size() ; i++)
			if (offers.get(i).getOfferer().getId() == offerer.getId())
			{
				o3 = offers.get(i);
				break;
			}
		assertNotNull(o3);
		assertEquals(o1.getBasePrice(), o3.getBasePrice());
		assertEquals(o1.getOfferer().getId(), o3.getOfferer().getId());
		assertEquals(c.getCardIndex(), o3.getOffer().getCardIndex());
		
		/*dealManager.removeOffer(o1.getId());
		gottenUser = dealManager.fetchPendingOffersForUser(offerer);
		assertEquals(gottenUser.getOffers().size(), 0);
		userManager.deleteUser(gottenUser.getId());
		cardsManager.removeCard(c.getCardIndex());
		*/
	}
	
	public void testBasicAcceptOffer()
	{
		User offerer = new User();
		offerer.setPseudo("testoffererBasic");
		offerer.setSha1Password("pipo");
		offerer.setSolde(0.f);
		offerer.setPremium(false);
		offerer = userManager.subscribe(offerer);
		
		User buyer = new User();
		buyer.setPseudo("testbuyerBasic");
		buyer.setSha1Password("pipo");
		buyer.setSolde(100.f);
		buyer.setPremium(false);
		buyer = userManager.subscribe(buyer);
		
		Carte c = new Carte();
		try {
			c.setCardIndex("50/1");
		} catch (poketrade.entities.subtypes.InvalidCardIndex e) {
			assert(false);
		}
		c.setNom("Pikachu");
		c = cardsManager.registerCard(c);
		
		offerer = dealManager.publishOffer(offerer.getId(), c.getCardIndex(), 80);
		
		PendingOffer offer = offerer.getOffers().get(0);
		assertFalse(offer.isConcluded());
		
		buyer = dealManager.concludeDeal(offerer.getOffers().get(0).getId(), buyer.getId());
		//offerer = userManager.handleLogin("testoffererBasic", "pipo");
		offerer = dealManager.fetchPendingOffersForUser(offerer);
		
		assertEquals(offerer.getSolde(), 80.f);
		assertEquals(buyer.getSolde(), 3.2f, 0.1);
		
		offer = offerer.getOffers().get(0);
		assertTrue(offer.isConcluded());
		assertEquals(offer.getBuyer().getId(), buyer.getId());
	}
	
	public void testOnePremiumAcceptOffer()
	{
		User offerer = new User();
		offerer.setPseudo("testoffererOnePremium");
		offerer.setSha1Password("pipo");
		offerer.setSolde(0.f);
		offerer.setPremium(true);
		offerer = userManager.subscribe(offerer);
		
		User buyer = new User();
		buyer.setPseudo("testbuyerOnePremium");
		buyer.setSha1Password("pipo");
		buyer.setSolde(100.f);
		buyer.setPremium(false);
		buyer = userManager.subscribe(buyer);
		
		Carte c = new Carte();
		try {
			c.setCardIndex("50/2");
		} catch (poketrade.entities.subtypes.InvalidCardIndex e) {
			assert(false);
		}
		c.setNom("Pikachu");
		c = cardsManager.registerCard(c);
		
		offerer = dealManager.publishOffer(offerer.getId(), c.getCardIndex(), 80);
		
		PendingOffer offer = offerer.getOffers().get(0);
		assertFalse(offer.isConcluded());
		
		buyer = dealManager.concludeDeal(offerer.getOffers().get(0).getId(), buyer.getId());
		offerer = dealManager.fetchPendingOffersForUser(offerer);
		
		assertEquals(offerer.getSolde(), 80.f);
		assertEquals(buyer.getSolde(), 12.f, 0.1);
		
		offer = offerer.getOffers().get(0);
		assertTrue(offer.isConcluded());
		assertEquals(offer.getBuyer().getId(), buyer.getId());
	}
	
	public void testTwoPremiumAcceptOffer()
	{
		User offerer = new User();
		offerer.setPseudo("testoffererTwoPremium");
		offerer.setSha1Password("pipo");
		offerer.setSolde(0.f);
		offerer.setPremium(true);
		offerer = userManager.subscribe(offerer);
		
		User buyer = new User();
		buyer.setPseudo("testbuyerTwoPremium");
		buyer.setSha1Password("pipo");
		buyer.setSolde(100.f);
		buyer.setPremium(true);
		buyer = userManager.subscribe(buyer);
		
		Carte c = new Carte();
		try {
			c.setCardIndex("50/3");
		} catch (poketrade.entities.subtypes.InvalidCardIndex e) {
			assert(false);
		}
		c.setNom("Pikachu");
		c = cardsManager.registerCard(c);
		
		offerer = dealManager.publishOffer(offerer.getId(), c.getCardIndex(), 80);
		
		PendingOffer offer = offerer.getOffers().get(0);
		assertFalse(offer.isConcluded());
		
		buyer = dealManager.concludeDeal(offerer.getOffers().get(0).getId(), buyer.getId());
		offerer = dealManager.fetchPendingOffersForUser(offerer);
		
		assertEquals(offerer.getSolde(), 80.f);
		assertEquals(buyer.getSolde(), 20.f);
		
		offer = offerer.getOffers().get(0);
		assertTrue(offer.isConcluded());
		assertEquals(offer.getBuyer().getId(), buyer.getId());
	}
	
	public void testNoFundingsAcceptOffer()
	{
		User offerer = new User();
		offerer.setPseudo("testoffererNoFunding");
		offerer.setSha1Password("pipo");
		offerer.setSolde(0.f);
		offerer.setPremium(true);
		offerer = userManager.subscribe(offerer);
		
		User buyer = new User();
		buyer.setPseudo("testbuyerNoFunding");
		buyer.setSha1Password("pipo");
		buyer.setSolde(100.f);
		buyer.setPremium(true);
		buyer = userManager.subscribe(buyer);
		
		Carte c = new Carte();
		try {
			c.setCardIndex("50/4");
		} catch (poketrade.entities.subtypes.InvalidCardIndex e) {
			assert(false);
		}
		c.setNom("Pikachu");
		c = cardsManager.registerCard(c);
		
		offerer = dealManager.publishOffer(offerer.getId(), c.getCardIndex(), 120);
		
		PendingOffer offer = offerer.getOffers().get(0);
		assertFalse(offer.isConcluded());
		
		User ret = dealManager.concludeDeal(offerer.getOffers().get(0).getId(), buyer.getId());
		assertNull(ret);
		offerer = dealManager.fetchPendingOffersForUser(offerer);
		
		assertEquals(offerer.getSolde(), 0.f);
		assertEquals(buyer.getSolde(), 100.f);
		
		offer = offerer.getOffers().get(0);
		assertFalse(offer.isConcluded());
	}
	
	public void testAddresses()
	{
		User test = new User();
		test.setPseudo("testUserAddress");
		test.setSha1Password("pipo");
		test.setSolde(0.f);
		test.setPremium(true);
		test= userManager.subscribe(test);
		
		assertTrue(userManager.getAddressList().size() > 0); 
	}
}
